package parser;
import java.util.*;
import java.io.*; 
import antlr.RecognitionException;
import antlr.Token;

public final class LambdaExpr extends Expr {
    
    int index;
    int defaults;
    List<Parameter2> parameters;
    boolean closure;
    Dictionary annotations;

    void delete(ByteStream out) throws RecognitionException {
        throw new RecognitionException("Cannot delete rvalue");
    }

    LambdaExpr(List<Parameter2> parameters, int index, Expr retType, boolean closure) throws RecognitionException {
        this.index = index;
        this.parameters = parameters;
        this.defaults = defaultCount(parameters);
        this.closure = closure;
        make_annotations(parameters, retType);
    }

    void make_annotations(List<Parameter2> parameters, Expr retType) {
        List<Expr> items = new ArrayList<Expr>();
        for(Parameter2 p : parameters) {
            if (p.type != null) {
                items.add(new Name(p.nameID));
                items.add(p.type);
            }
        }
        if (retType != null) {
            items.add(new Name(NameTable.getIndex("return")));
            items.add(retType);  
        }
        this.annotations = new Dictionary(items);
    }

    void write(ByteStream out) throws RecognitionException {
        for(Parameter2 p : parameters) {
            if (p.value != null)
                p.value.write(out);
        }
        int defs = defaultCount(parameters);
        if (defs == 0) {
            out.write(Opcodes.EMPTY_TUPLE);
        } else {
            out.write(Opcodes.PACK);
            out.write(defs);
        }
        annotations.write(out);
        if (closure) {
            out.write(Opcodes.MAKE_CLOSURE);
        } else {
            out.write(Opcodes.MAKE_FUNC);
        }
        out.write(index);
    }
     
    int defaultCount(List<Parameter2> parameters) throws RecognitionException {
        int count = 0;
        boolean seen_default = false;
        for (Parameter2 p : parameters) {
            if (p instanceof TupleParameter || p instanceof DictParameter)
                seen_default = false;
            if (p.value == null) {
                if (seen_default) {
                    throw new RecognitionException("Cannot have parameter without default after one with");
                }
            } else {
                seen_default = true;
                count++;
            }
        }
        return count;
    }
    
    void writeLHS(ByteStream out) throws RecognitionException {
        throw new RecognitionException("Cannot assign to a lambda expression");
    }
    
}
